package org.lhh.server.core.codec.trans;

import org.apache.commons.lang3.StringUtils;
import org.pentaho.di.base.AbstractMeta;
import org.pentaho.di.cluster.SlaveServer;
import org.pentaho.di.core.logging.LogLevel;
import org.pentaho.di.trans.TransExecutionConfiguration;

import java.util.*;

public class TransExecutionConfigurationCodec {

    private boolean exec_local;
    private boolean exec_remote;
    private String remote_server;
    private boolean pass_export;
    private boolean exec_cluster;
    private boolean cluster_post;
    private boolean cluster_prepare;
    private boolean cluster_start;
    private boolean cluster_show_trans;
    private boolean safe_mode;
    private String log_level;
    private boolean clear_log;
    private boolean gather_metrics;
    private boolean log_remote_execution_locally;

    private List<Map<String, String>> paramNames;
    private List<Map<String, String>> variableNames;
    private List<Map<String, String>> argumentNames;


    public static TransExecutionConfigurationCodec encode(TransExecutionConfiguration executionConfiguration) {
        TransExecutionConfigurationCodec transExecutionConfigurationCodec = new TransExecutionConfigurationCodec();
        transExecutionConfigurationCodec.setExec_local(executionConfiguration.isExecutingLocally());
        transExecutionConfigurationCodec.setExec_remote(executionConfiguration.isExecutingRemotely());
        if (executionConfiguration.getRemoteServer() != null) {
            transExecutionConfigurationCodec.setRemote_server(executionConfiguration.getRemoteServer().getName());
        }
        transExecutionConfigurationCodec.setPass_export(executionConfiguration.isPassingExport());
        transExecutionConfigurationCodec.setExec_cluster(executionConfiguration.isExecutingClustered());
        transExecutionConfigurationCodec.setCluster_post(executionConfiguration.isClusterPosting());
        transExecutionConfigurationCodec.setCluster_prepare(executionConfiguration.isClusterPreparing());
        transExecutionConfigurationCodec.setCluster_start(executionConfiguration.isClusterStarting());
        transExecutionConfigurationCodec.setCluster_show_trans(executionConfiguration.isClusterShowingTransformation());
        transExecutionConfigurationCodec.setSafe_mode(executionConfiguration.isSafeModeEnabled());
        transExecutionConfigurationCodec.setLog_level(executionConfiguration.getLogLevel().getCode());
        transExecutionConfigurationCodec.setClear_log(executionConfiguration.isClearingLog());
        transExecutionConfigurationCodec.setGather_metrics(executionConfiguration.isGatheringMetrics());
        transExecutionConfigurationCodec.setLog_remote_execution_locally(executionConfiguration.isLogRemoteExecutionLocally());

        List<Map<String, String>> paramNameMaps = new ArrayList<>();
        List<String> paramNames = new ArrayList<>(executionConfiguration.getParams().keySet());
        Collections.sort(paramNames);
        for (String name : paramNames) {
            String value = executionConfiguration.getParams().get(name);
            Map<String, String> paramNameMap = new HashMap<>();
            paramNameMap.put("name", name);
            paramNameMap.put("value", value);
            paramNameMaps.add(paramNameMap);
        }
        transExecutionConfigurationCodec.setParamNames(paramNameMaps);

        List<Map<String, String>> variableNameMaps = new ArrayList<>();
        List<String> variableNames = new ArrayList<>(executionConfiguration.getVariables().keySet());
        Collections.sort(variableNames);
        for (String name : variableNames) {
            String value = executionConfiguration.getVariables().get(name);
            Map<String, String> variableNameMap = new HashMap<>();
            variableNameMap.put("name", name);
            variableNameMap.put("value", value);
            variableNameMaps.add(variableNameMap);
        }
        transExecutionConfigurationCodec.setVariableNames(variableNameMaps);

        List<Map<String, String>> argumentNameMaps = new ArrayList<>();
        List<String> argumentNames = new ArrayList<>(executionConfiguration.getArguments().keySet());
        Collections.sort(argumentNames);
        for (String name : argumentNames) {
            String value = executionConfiguration.getArguments().get(name);
            Map<String, String> argumentNameMap = new HashMap<>();
            argumentNameMap.put("name", name);
            argumentNameMap.put("value", value);
            argumentNameMaps.add(argumentNameMap);
        }
        transExecutionConfigurationCodec.setArgumentNames(argumentNameMaps);

        return transExecutionConfigurationCodec;
    }

    public static TransExecutionConfiguration decode(TransExecutionConfigurationCodec transExecutionConfigurationCodec, AbstractMeta meta) {
        TransExecutionConfiguration executionConfiguration = new TransExecutionConfiguration();
        executionConfiguration.setExecutingLocally(transExecutionConfigurationCodec.isExec_local());
        executionConfiguration.setExecutingRemotely(transExecutionConfigurationCodec.isExec_remote());
        if (executionConfiguration.isExecutingRemotely()) {
            String remoteServer = transExecutionConfigurationCodec.getRemote_server();
            if (StringUtils.isNotEmpty(remoteServer)) {
                SlaveServer slaveServer = meta.findSlaveServer(remoteServer);
                executionConfiguration.setRemoteServer(slaveServer);
            }
        }
        executionConfiguration.setPassingExport(transExecutionConfigurationCodec.isPass_export());
        executionConfiguration.setExecutingClustered(transExecutionConfigurationCodec.isExec_cluster());
        executionConfiguration.setClusterPosting(transExecutionConfigurationCodec.isCluster_post());
        executionConfiguration.setClusterPreparing(transExecutionConfigurationCodec.isCluster_prepare());
        executionConfiguration.setClusterShowingTransformation(transExecutionConfigurationCodec.isCluster_show_trans());
        executionConfiguration.setClusterStarting(transExecutionConfigurationCodec.isCluster_start());
        executionConfiguration.setSafeModeEnabled(transExecutionConfigurationCodec.isSafe_mode());
        executionConfiguration.setLogLevel(LogLevel.getLogLevelForCode(transExecutionConfigurationCodec.getLog_level()));
        executionConfiguration.setClearingLog(transExecutionConfigurationCodec.isClear_log());
        executionConfiguration.setGatheringMetrics(transExecutionConfigurationCodec.isGather_metrics());
        executionConfiguration.setLogRemoteExecutionLocally(transExecutionConfigurationCodec.log_remote_execution_locally);
        return executionConfiguration;
    }

    private static void setMap(Map<String, String> target, List<Map<String, String>> maps) {
        for (Map<String, String> map : maps) {
            String varName = map.get("name");
            String varValue = map.get("value");
            if (StringUtils.isNotEmpty(varName) && StringUtils.isNotEmpty(varValue)) {
                target.put(varName, varValue);
            }
        }
    }

    public boolean isExec_local() {
        return exec_local;
    }

    public void setExec_local(boolean exec_local) {
        this.exec_local = exec_local;
    }

    public boolean isExec_remote() {
        return exec_remote;
    }

    public void setExec_remote(boolean exec_remote) {
        this.exec_remote = exec_remote;
    }

    public String getRemote_server() {
        return remote_server;
    }

    public void setRemote_server(String remote_server) {
        this.remote_server = remote_server;
    }

    public boolean isPass_export() {
        return pass_export;
    }

    public void setPass_export(boolean pass_export) {
        this.pass_export = pass_export;
    }

    public boolean isExec_cluster() {
        return exec_cluster;
    }

    public void setExec_cluster(boolean exec_cluster) {
        this.exec_cluster = exec_cluster;
    }

    public boolean isCluster_post() {
        return cluster_post;
    }

    public void setCluster_post(boolean cluster_post) {
        this.cluster_post = cluster_post;
    }

    public boolean isCluster_prepare() {
        return cluster_prepare;
    }

    public void setCluster_prepare(boolean cluster_prepare) {
        this.cluster_prepare = cluster_prepare;
    }

    public boolean isCluster_start() {
        return cluster_start;
    }

    public void setCluster_start(boolean cluster_start) {
        this.cluster_start = cluster_start;
    }

    public boolean isCluster_show_trans() {
        return cluster_show_trans;
    }

    public void setCluster_show_trans(boolean cluster_show_trans) {
        this.cluster_show_trans = cluster_show_trans;
    }

    public boolean isSafe_mode() {
        return safe_mode;
    }

    public void setSafe_mode(boolean safe_mode) {
        this.safe_mode = safe_mode;
    }

    public String getLog_level() {
        return log_level;
    }

    public void setLog_level(String log_level) {
        this.log_level = log_level;
    }

    public boolean isClear_log() {
        return clear_log;
    }

    public void setClear_log(boolean clear_log) {
        this.clear_log = clear_log;
    }

    public boolean isGather_metrics() {
        return gather_metrics;
    }

    public void setGather_metrics(boolean gather_metrics) {
        this.gather_metrics = gather_metrics;
    }

    public boolean isLog_remote_execution_locally() {
        return log_remote_execution_locally;
    }

    public void setLog_remote_execution_locally(boolean log_remote_execution_locally) {
        this.log_remote_execution_locally = log_remote_execution_locally;
    }

    public List<Map<String, String>> getParamNames() {
        return paramNames;
    }

    public void setParamNames(List<Map<String, String>> paramNames) {
        this.paramNames = paramNames;
    }

    public List<Map<String, String>> getVariableNames() {
        return variableNames;
    }

    public void setVariableNames(List<Map<String, String>> variableNames) {
        this.variableNames = variableNames;
    }

    public List<Map<String, String>> getArgumentNames() {
        return argumentNames;
    }

    public void setArgumentNames(List<Map<String, String>> argumentNames) {
        this.argumentNames = argumentNames;
    }

}
